<script setup>
import uniIcons from '@dcloudio/uni-ui/lib/uni-icons/uni-icons.vue'
import uniDrawer from '@dcloudio/uni-ui/lib/uni-drawer/uni-drawer.vue'
import { ref, computed, onMounted, onUnmounted } from 'vue'
import DrawerContent from '@/components/DrawerContent/index.vue'
import ChatOptionsPopover from '@/components/ChatOptionsPopover/index.vue'
import { getRoomDetail, sendMessage, generateImage } from '@/api/chat'
import { useStore } from 'vuex'
import { onLoad, onUnload } from '@dcloudio/uni-app'
import ChatInput from '@/components/chat/ChatInput.vue'
import useSafeAreaInsets from '@/composables/useSafeAreaInsets'
import Messages from '@/components/chat/Messages.vue'
import { useAIModel, useRandoms } from './hooks'
import ConversationGroup from '@/components/ConversationGroup'
const { VITE_DEFAULT_AI_MODEL } = import.meta.env

const props = defineProps({
  // gpt || dalle
  chatMode: {
    type: String,
  },
})

// let routes = getCurrentPages();
// let {} = routes[routes.length - 1] 


const store = useStore()
const drawerRef = ref(null)
const drawerVisible = ref(false)
const messageInputFocus = ref(false)

function handleDrawerChange(val) {
  drawerVisible.value = val
}

const safeAreaInsets = useSafeAreaInsets()
const menuButtonInfo = uni.getMenuButtonBoundingClientRect?.()

const paddingTop = computed(() => {
  return (menuButtonInfo?.height ?? 0) + (safeAreaInsets.value?.top ?? 0)
})

const generatingMessage = computed(() => store.state.chat.generatingMessage)
const history = computed(() => store.state.chat.history)
const currentRoomId = computed(() => store.state.chat.currentRoomId)
const isGenerating = computed(() => store.state.chat.isGenerating)
const isGeneratingImage = computed(() => store.state.chat.isGeneratingImage)

const { AIModel, toggleByVersionAction } = useAIModel(props)

let loaded = false
onLoad(async (option) => {
  loaded = true
  const roomId = option.room
  const chatMode = option.chatMode;
  if(!chatMode && !roomId) {
  uni.redirectTo({ url: `/pages/index/index?chatMode=${VITE_DEFAULT_AI_MODEL}`, })
}


  if (roomId) {
    store.commit('chat/setCurrentRoomId', roomId)

    uni.showLoading({ mask: true })
    await store.dispatch('chat/setRoomChatHistory', roomId)
    uni.hideLoading()
    const resp = await getRoomDetail(roomId)

    resp.data && store.commit('chat/setRoomDetail', resp.data)

    toggleByVersionAction(resp.data?.version)
  } else {
    store.commit('chat/resetRoom')
  }
})

function handleFinish() {
  if (history.value.length === 1) {
    store.dispatch('chat/updateRoomList')
  }
  generatingMessage.value &&
    store.commit('chat/pushMessage', {
      role: 'assistant',
      message: generatingMessage.value,
    })
  store.commit('chat/setGeneratingMessage', '')
  store.commit('chat/setIsGenerating', false)
  messageInputFocus.value = true
}

onUnload(() => {
  loaded = false
  isGenerating.value & handleFinish()
  isGeneratingImage.value && store.commit('chat/setIsGeneratingImage', false)
})

let abortController =
  typeof AbortController !== 'undefined' ? new AbortController() : {}
let sendReq = null

function handleAbortGenerating() {
  abortController.abort()
  handleFinish()
  // #ifdef WEB
  abortController =
    typeof AbortController !== 'undefined' ? new AbortController() : {}
  // #endif

  // #ifdef MP-WEIXIN
  abortController = {
    abort: () => {
      sendReq?.abort()
    },
  }
  // #endif
}

async function handleGenerateImage({ msg }) {
  store.commit('chat/setIsGeneratingImage', true)
  const resp = await generateImage({
    msg,
    type: 1,
    version: AIModel.value.version,
    firstMessage: history.value.length <= 1,
    roomId: currentRoomId.value,
  })
  store.commit('chat/setIsGeneratingImage', false)
  if (resp.data?.length > 0) {
    loaded &&
      store.commit('chat/pushMessage', {
        role: 'assistant',
        message: '',
        files: resp.data.map((datum) => ({
          fileUrl: datum.url,
          type: 0,
          prompt: datum.revisedPrompt,
        })),
      })
  }
}

async function handleSendMessage({ msg, files }) {
  store.commit('chat/setRefreshConversation', msg)
  messageInputFocus.value = false
  store.commit('chat/pushMessage', {
    role: 'user',
    message: msg,
    files,
  })

  if (!currentRoomId.value) {
    uni.showLoading({ mask: true })
    await store.dispatch('chat/createRoom', AIModel.value.version)
    uni.hideLoading()
    store.dispatch('chat/updateRoomList')
  }

  if (props.chatMode === 'DALL·E') {
    handleGenerateImage({ msg })
    return
  }

  store.commit('chat/setIsGenerating', true)

  function onMessage(rawData) {
    if (!loaded) return

    let data
    try {
      data = JSON.parse(rawData)
    } catch (e) {
      return
    }
    const { choices } = data
    const { finish_reason: finishReason } = choices[0]
    if (finishReason) {
      handleFinish()
      return
    }
    const { content = '' } = choices[0].delta
    console.log('appendGeneratingMessage', content)
    store.commit('chat/appendGeneratingMessage', content)
  }

  sendReq = await sendMessage({
    data: {
      msg,
      type: 1,
      version: AIModel.value.version,
      firstMessage: history.value.length <= 1,
      roomId: currentRoomId.value,
      addFileList: files,
    },
    onMessage,
    signal: abortController.signal,
  })

  // #ifdef MP-WEIXIN
  abortController = {
    abort: () => {
      sendReq.abort()
    },
  }
  // #endif
}

function handleCreateRoom() {
  uni.navigateTo({ url: '/pages/index/index' })
}

const keyboardHeight = ref(0)

function handleVisualViewportResize(event) {
  keyboardHeight.value = Math.max(0, window.innerHeight - event.target.height)
}
onUnmounted(() => {
  // #ifdef WEB
  window.visualViewport.removeEventListener(
    'resize',
    handleVisualViewportResize,
  )
  // #endif
})

onMounted(() => {
  // #ifdef WEB
  window.visualViewport.addEventListener('resize', handleVisualViewportResize)

  // #endif
})
function handleChatInputFocus(e) {
  messageInputFocus.value = true
  // #ifdef MP-WEIXIN
  keyboardHeight.value = e.detail.height
  // #endif
}
function handleChatInputBlur() {
  messageInputFocus.value = false
  keyboardHeight.value = 0
}

const { randomList } = useRandoms()
</script>

<template>
  <view
    class="flex h-full overflow-hidden text-base md:gap-3"
    :style="{
      paddingBottom: `${(safeAreaInsets?.bottom ?? 0) + keyboardHeight}px`,
    }"
  >
    <match-media :min-width="768">
      <DrawerContent @send-message="handleSendMessage" />
    </match-media>
    <view
      :class="{ 'translate-x-72 translate-y-0': drawerVisible }"
      class="flex w-full min-w-0 flex-col transition"
      :style="{
        paddingTop: `${paddingTop}px`,
      }"
    >
      <view class="flex items-center justify-between py-3 pl-3 pr-4">
        <view class="flex items-center gap-3 text-lg">
          <match-media :max-width="768">
            <uni-icons type="bars" size="24" @click="drawerRef.open()" />
          </match-media>
          <view>
            <text class="ml-1.5">
              {{ AIModel?.name ?? '' }}
            </text>
          </view>
        </view>
        <view class="flex items-center gap-3">
          <uni-icons type="compose" size="24" @click="handleCreateRoom" />
          <ChatOptionsPopover />
        </view>
      </view>
      <view class="chat-history flex flex-grow justify-center overflow-hidden">
        <!-- <Messages v-if="currentRoomId" class="conversation-container" /> -->
        <ConversationGroup
          v-if="currentRoomId"
          @send-message="handleSendMessage"
        ></ConversationGroup>
        <view v-else class="conversation-container">
          <view class="t_center">
            <view class="flex justify-center">
              <view
                class="mb-3 flex size-12 items-center justify-center rounded-full border bg-white"
              >
                <view class="size-8 rounded-full bg-zinc-950" />
              </view>
            </view>
            <view class="mb-5 text-2xl font-medium">
              How can I help you today?
            </view>
          </view>

          <view class="column_2 gap_sm grid">
            <view v-for="item in randomList" :key="item" class="grid-item">
              <view class="p_sm border_lighter radius_sm pointer" @click="()=> handleSendMessage({msg: item.question, files:[]})">
                <view>{{ item.question }}</view>
              </view>
            </view>
            
          </view>
        </view>
      </view>
      <div class="flex justify-center">
        <ChatInput
          class="conversation-container"
          :focus="messageInputFocus"
          @send-message="handleSendMessage"
          @focus="handleChatInputFocus"
          @blur="handleChatInputBlur"
          @abort-generating="handleAbortGenerating"
        />
      </div>
    </view>
    <match-media :max-width="768">
      <uni-drawer ref="drawerRef" mode="left" @change="handleDrawerChange">
        <DrawerContent @close="drawerRef.close()" />
      </uni-drawer>
    </match-media>
  </view>
</template>

<style>
page {
  height: 100%;
}
::v-deep .hljs-pre {
  padding: 36rpx;
  margin: 24rpx 0;
  border-radius: 16rpx;
  background: #fafafa;
  display: flex;
  justify-content: space-between;
}
::v-deep .hljs-code {
  overflow-x: auto;
  white-space: pre;
  word-wrap: normal;
}

::v-deep .hljs-code::-webkit-scrollbar {
  display: none;
}
::v-deep .hljs-pre::-webkit-scrollbar {
  display: none;
}

.conversation-container {
  max-width: 712px;
  width: 100%;
}
</style>
